# -*- coding: utf-8 -*-
# @Author: Jerry
# @Date:   2022-02-24 10:04:08
# @Last Modified by:   Jerry
# @Last Modified time: 2022-03-01 15:30:46

# **********
'''
图像平滑
学会： - 使用各种低通滤镜模糊图像 - 将定制的滤镜应用于图像（2D卷积）
'''

# **********
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
import os
rootpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
datapath = os.path.join(rootpath,'data')
imgpath = lambda name: os.path.join(datapath,name)


# **********
'''
2D卷积（图像过滤）
与一维信号一样，还可以使用各种低通滤波器（LPF），高通滤波器（HPF）等对图像进行滤波。
LPF有助于消除噪声，使图像模糊等。
HPF滤波器有助于在图像中找到边缘。

OpenCV函数 cv.filter2D 用于 将内核与图像进行卷积。 内核通常是个矩阵
操作过程：
  保持这个内核在一个像素上，将所有低于这个内核的25个像素相加，取其平均值，
  然后用新的平均值替换中心像素。对图像中的所有像素继续此操作
'''
def filter2d_test():
    img = cv.imread(imgpath('opencv-logo-white.png'))
    kenel = np.ones((5,5),np.float32)/25 # 一个5x5的矩阵 取平均值
    # cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) -> dst
    dst = cv.filter2D(img,-1,kenel)
    plt.subplot(121),plt.imshow(img),plt.title('img')
    plt.xticks([]),plt.yticks([])
    plt.subplot(122),plt.imshow(dst),plt.title('dst')
    plt.xticks([]),plt.yticks([])
    plt.show()


# **********
'''
图像模糊（图像平滑）
  通过将图像与低通滤波器内核进行卷积来实现图像模糊。这对于消除噪音很有用。
  它实际上从图像中消除了高频部分（例如噪声，边缘）。因此，在此操作中边缘有些模糊。
OpenCV主要提供四种类型的模糊技术:
  1. 平均：通过cv.blur()或者cv.boxFilter()完成
       这是通过将图像与归一化框滤镜进行卷积来完成的。
       它仅获取内核区域下所有像素的平均值，并替换中心元素。
  2. 高斯模糊：通过功能 cv.GaussianBlur() 完成，如果需要，可以使用函数 cv.getGaussianKernel() 创建高斯内核。
       高斯模糊对于从图像中去除高斯噪声非常有效。
       可以看到，高斯滤波器采用像素周围的邻域并找到其高斯加权平均值。
       高斯滤波器仅是空间的函数，也就是说，滤波时会考虑附近的像素。
       它不考虑像素是否具有几乎相同的强度。它不考虑像素是否是边缘像素。
       因此它也模糊了边缘，
  3. 中位模糊：通过函数 cv.medianBlur()完成功能
       提取内核区域下所有像素的中值，并将中心元素替换为该中值。
       这对于消除图像中的椒盐噪声非常有效。
  4. 双边滤波：cv.bilateralFilter() 在去除噪声的同时保持边缘清晰锐利非常有效。但是，与其他过滤器相比，该操作速度较慢。
       双边滤波器在空间中也采用高斯滤波器，但是又有一个高斯滤波器，它是像素差的函数。
       空间的高斯函数确保仅考虑附近像素的模糊，
       而强度差的高斯函数确保仅考虑强度与中心像素相似的那些像素的模糊。由于边缘的像素强度变化较大，因此可以保留边缘。
       有关双边过滤的详细信息：http://people.csail.mit.edu/sparis/bf_course/
'''
# **********
# 平均
def blur_boxFilter_test():
    img = cv.imread(imgpath('opencv-logo-white.png'))
    # 平均模糊
    blur = cv.blur(img,(5,5)) # 内核大小为5x5
    # 高斯模糊
    # blur = cv.GaussianBlur(img,(5,5),0)
    # 中位模糊
    # median = cv.medianBlur(img,5)
    # 双边滤波
    # blur = cv.bilateralFilter(img,9,75,75)
    img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
    plt.subplot(121),plt.imshow(img),plt.title('img')
    plt.xticks([]),plt.yticks([])

    blur = cv.cvtColor(blur,cv.COLOR_BGR2RGB)
    plt.subplot(122),plt.imshow(blur),plt.title('blur')
    plt.xticks([]),plt.yticks([])
    plt.show()





if __name__ == '__main__':
    # filter2d_test()
    # blur_boxFilter_test()
    # gaussianblur_test()
    medianBlur_test()


